---
title: useState Hook
description: "Details about the useState React hook in ReScript"
canonical: "/docs/react/hooks-state"
section: "Hooks & State Management"
order: 3
---

# useState

<Intro>

`React.useState` returns a stateful value, and a function to update it.

</Intro>

## Usage

<CodeTab labels={["ReScript", "JS Output"]}>

```res
let (state, setState) = React.useState(_ => initialState)
```

```js
var match = React.useState(function () {
  return initialState;
});

var state = match[0];

var setState = match[1];
```

</CodeTab>

During the initial render, the returned state `state` is the same as the value passed as the first argument (initialState).

The `setState` function can be passed down to other components as well, which is useful for e.g. setting the state of a parent component by its children.

## Examples

### Using State for a Text Input

```res example
@react.component
let make = () => {
  let (text, setText) = React.useState(_ => "");

  let onChange = evt => {
    ReactEvent.Form.preventDefault(evt)
    let value = ReactEvent.Form.target(evt)["value"]
    setText(_prev => value);
  }

  <div>
    <input onChange value=text />
  </div>
};
```

### Passing `setState` to a Child Component

In this example, we are creating a `ThemeContainer` component that manages a `darkmode` boolean state and passes the `setDarkmode` function to a `ControlPanel` component to trigger the state changes.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// ThemeContainer.res
module ControlPanel = {
  @react.component
  let make = (~setDarkmode, ~darkmode) => {
    let onClick = evt => {
      ReactEvent.Mouse.preventDefault(evt)
      setDarkmode(prev => !prev)
    }

    let toggleText = "Switch to " ++ ((darkmode ? "light" : "dark") ++ " theme")

    <div> <button onClick> {React.string(toggleText)} </button> </div>
  }
}

@react.component
let make = (~content) => {
  let (darkmode, setDarkmode) = React.useState(_ => false)

  let className = darkmode ? "theme-dark" : "theme-light"

  <div className>
    <section>
      <h1> {React.string("More Infos about ReScript")} </h1> content
    </section>
    <ControlPanel darkmode setDarkmode />
  </div>
}
```

```js
function ControlPanel(Props) {
  var setDarkmode = Props.setDarkmode;
  var darkmode = Props.darkmode;
  var onClick = function (evt) {
    evt.preventDefault();
    return Curry._1(setDarkmode, function (prev) {
      return !prev;
    });
  };
  var toggleText = "Switch to " + ((darkmode ? "light" : "dark") + " theme");
  return React.createElement(
    "div",
    undefined,
    React.createElement(
      "button",
      {
        onClick: onClick,
      },
      toggleText,
    ),
  );
}

function ThemeContainer(Props) {
  var content = Props.content;
  var match = React.useState(function () {
    return false;
  });
  var darkmode = match[0];
  var className = darkmode ? "theme-dark" : "theme-light";
  return React.createElement(
    "div",
    {
      className: className,
    },
    React.createElement(
      "section",
      undefined,
      React.createElement("h1", undefined, "More Infos about ReScript"),
      content,
    ),
    React.createElement(Playground$ControlPanel, {
      setDarkmode: match[1],
      darkmode: darkmode,
    }),
  );
}
```

</CodeTab>

Note that whenever `setDarkmode` is returning a new value (e.g. switching from `true` -> `false`), it will cause a re-render for `ThemeContainer`'s `className` and the toggle text of its nested `ControlPanel`.
